package org.dromara.common.core.utils.file;

import cn.hutool.json.JSONUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONArray;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.stream.Collectors;

@Slf4j
public class FFMpegUtils {

    /**
     * 使用 ffprobe 获取视频详细信息
     * @param filePath 视频文件路径
     * @return 视频信息对象
     * @throws Exception 解析或命令异常
     */
    public static VideoFileInfo getVideoInfo(String filePath) {
        try {

            ProcessBuilder pb = new ProcessBuilder(
                "ffprobe", "-v", "quiet", "-print_format", "json",
                "-show_format", "-show_streams", filePath
            );
            Process process = pb.start();
            String json = new BufferedReader(new InputStreamReader(process.getInputStream()))
                .lines().collect(Collectors.joining());
            process.waitFor();

            JSONObject root = JSONUtil.parseObj(json);
            JSONObject format = root.getJSONObject("format");
            JSONArray streams = root.getJSONArray("streams");

            VideoFileInfo info = new VideoFileInfo();
            info.filePath = filePath;
            info.size = format.getLong("size", 0L);
            info.bitRate = format.getLong("bit_rate", 0L);
            info.resolutionLabel = getResolutionLabel(info.height);

            // ========== 格式处理 ==========
            info.formatCandidates = format.getStr("format_name");
            info.formatDesc = format.getStr("format_long_name");
            String fullPath = format.getStr("filename");
            info.formatName = fullPath.substring(fullPath.lastIndexOf('.') + 1).toLowerCase();

            // ========== 时长处理 ==========
            info.duration = format.getDouble("duration", 0.0);
            info.durationMillis = (long) (info.duration * 1000);
            info.durationFormatted = formatDuration(info.duration);

            // ========== 流遍历 ==========
            for (int i = 0; i < streams.size(); i++) {
                JSONObject stream = streams.getJSONObject(i);
                String type = stream.getStr("codec_type");
                if ("video".equals(type)) {
                    info.videoCodec = stream.getStr("codec_name");
                    info.width = stream.getInt("width", 0);
                    info.height = stream.getInt("height", 0);
                    info.resolutionLabel = getResolutionLabel(info.height);
                    info.frameRate = stream.getStr("avg_frame_rate");
                    info.videoBitRate = stream.getLong("bit_rate", 0L);
                } else if ("audio".equals(type)) {
                    info.audioCodec = stream.getStr("codec_name");
                    info.channels = stream.getInt("channels", 0);
                    info.sampleRate = stream.getInt("sample_rate", 0);
                    info.audioBitRate = stream.getLong("bit_rate", 0L);
                }
            }

            return info;

        }catch (Exception e){
             log.error("获取视频详细信息失败", e);
        }

        return null;

    }

    private static String formatDuration(double seconds) {
        int hrs = (int) seconds / 3600;
        int mins = ((int) seconds % 3600) / 60;
        double secs = seconds % 60;
        return String.format("%02d:%02d:%06.3f", hrs, mins, secs);
    }

    private static String getResolutionLabel(int height) {
        if (height >= 2160) return "4K (2160p)";
        if (height >= 1440) return "2K (1440p)";
        if (height >= 1080) return "1080p";
        if (height >= 720) return "720p";
        if (height >= 480) return "480p";
        if (height >= 360) return "360p";
        return "Low";
    }

    /**
     * 生成精灵图并返回相关信息
     *
     * @param videoFilePath  视频文件路径
     * @param videoDuration  视频时长（单位：秒）
     * @param videoWidth     视频宽度
     * @param videoHeight    视频高度
     * @param outputFilePath 输出精灵图路径
     * @return JSON 格式的雪碧图信息
     */
    public static JSONObject generateSprite(String videoFilePath, double videoDuration, int videoWidth, int videoHeight, String outputFilePath) throws IOException, InterruptedException {
        // 1. 计算每个预览图的标准宽度和高度（业绩标准尺寸）
        int thumbnailWidth = 90;  // 业绩标准宽度
        double aspectRatio = (double) videoWidth / videoHeight;
        int thumbnailHeight = (int) (thumbnailWidth / aspectRatio);  // 按比例计算高度

        // 2. 计算所需总帧数（假设精灵图的总宽度不超过 1000px，计算适合的视频帧数）
        int maxWidthInSprites = 1000;  // 精灵图最大宽度（可根据需求调整）
        int maxFramesPerRow = maxWidthInSprites / thumbnailWidth;  // 每行可以放多少帧
        int totalFrames = (int) Math.ceil(videoDuration / (double) (videoDuration / maxFramesPerRow));  // 总帧数

        // 3. 根据总帧数，计算每帧的间隔
        double frameInterval = videoDuration / totalFrames;  // 每帧的时间间隔

        // 4. 计算精灵图的行列数
        int rows = (int) Math.ceil(Math.sqrt(totalFrames));  // 精灵图的行数
        int cols = (int) Math.ceil((double) totalFrames / rows);  // 精灵图的列数

        ProcessBuilder pb = new ProcessBuilder(new String[]{
            "ffmpeg",
            "-i", videoFilePath,
            "-vf", String.format("fps=1/%f,scale=%d:%d,tile=%dx%d",
            frameInterval,
            thumbnailWidth,
            thumbnailHeight,
            cols,
            rows),
            "-loglevel", "error", // 只输出错误信息（减少日志量）
            "-y", // 覆盖输出文件
            outputFilePath
        });
        Process process = pb.start();
        process.waitFor();

        // 7. 构建返回的 JSON 对象
        JSONObject result = new JSONObject();
        JSONArray urls = new JSONArray();
        urls.put(outputFilePath); // 假设只有一张精灵图，若有多个则添加到此列表中

        result.put("urls", urls);
        result.put("pic_num", totalFrames);  // 预览图总帧数
        result.put("row", rows);             // 每张雪碧图的行数
        result.put("col", cols);             // 每张雪碧图的列数
        result.put("height", thumbnailHeight); // 每帧的高度
        result.put("width", thumbnailWidth);  // 每帧的宽度

        // 返回 JSON 格式结果
        return result;
    }



    public static void main(String[] args) throws Exception {
        String path = "\"C:\\Users\\15229\\Desktop\\video.mp4\"";
        VideoFileInfo info = getVideoInfo(path);
        System.out.println(info);
        System.out.println("📂 文件路径: " + info.filePath);
        System.out.println("🕒 时长: " + info.duration + " 秒");
        System.out.println("🎥 视频: " + info.videoCodec + " - " + info.width + "x" + info.height + " @ " + info.frameRate);
        System.out.println("🎧 音频: " + info.audioCodec + ", " + info.channels + " 声道, " + info.sampleRate + " Hz");
        System.out.println("📦 大小: " + info.size + " 字节");

        // 示例：生成精灵图
//        File tempFile = File.createTempFile("temp_", ".jpg");
        String videoFilePath = path;  // 视频文件路径
        double videoDuration = info.duration;                // 视频时长（秒）
        int videoWidth = info.width;                       // 视频宽度
        int videoHeight = info.height;                      // 视频高度
        String outputFilePath = "D:\\bb-file\\2025/04/27/1.png"; // 输出精灵图路径

        // 调用生成精灵图的方法并返回 JSON 格式结果
        JSONObject spriteInfo = generateSprite(videoFilePath, videoDuration, videoWidth, videoHeight, outputFilePath);

        // 输出生成的 JSON
        System.out.println(spriteInfo.toString());  // 输出格式化后的 JSON

    }
}
